summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2023-04-12 07:03:19 +0200
committerbunnei <bunneidev@gmail.com>2023-06-03 09:05:50 +0200
commit4006468f7368d0afe51be11a466e5b33c62e362d (patch)
treeca0294e6f596aa09a05352ad56687a41de60a764
parentandroid: vulkan_debug_callback: Ignore many innocuous errors. (diff)
downloadyuzu-4006468f7368d0afe51be11a466e5b33c62e362d.tar
yuzu-4006468f7368d0afe51be11a466e5b33c62e362d.tar.gz
yuzu-4006468f7368d0afe51be11a466e5b33c62e362d.tar.bz2
yuzu-4006468f7368d0afe51be11a466e5b33c62e362d.tar.lz
yuzu-4006468f7368d0afe51be11a466e5b33c62e362d.tar.xz
yuzu-4006468f7368d0afe51be11a466e5b33c62e362d.tar.zst
yuzu-4006468f7368d0afe51be11a466e5b33c62e362d.zip
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress.kt46
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ShaderProgressViewModel.kt31
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ui/ShaderProgressDialogFragment.kt101
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt12
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt1
-rw-r--r--src/android/app/src/main/jni/config.cpp4
-rw-r--r--src/android/app/src/main/jni/id_cache.cpp27
-rw-r--r--src/android/app/src/main/jni/id_cache.h5
-rw-r--r--src/android/app/src/main/jni/native.cpp18
-rw-r--r--src/android/app/src/main/res/layout/dialog_progress_bar.xml9
-rw-r--r--src/android/app/src/main/res/values/strings.xml7
12 files changed, 258 insertions, 4 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
index 3ab685b9b..1e654777a 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
@@ -42,6 +42,7 @@ object NativeLibrary {
const val Player8Device = 7
const val ConsoleDevice = 8
+ @JvmField
var sEmulationActivity = WeakReference<EmulationActivity?>(null)
init {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress.kt
new file mode 100644
index 000000000..9b665c7a0
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress.kt
@@ -0,0 +1,46 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.disk_shader_cache
+
+import org.yuzu.yuzu_emu.NativeLibrary
+import org.yuzu.yuzu_emu.R
+import org.yuzu.yuzu_emu.disk_shader_cache.ui.ShaderProgressDialogFragment
+
+object DiskShaderCacheProgress {
+ val finishLock = Object()
+ private lateinit var fragment: ShaderProgressDialogFragment
+
+ private fun prepareDialog() {
+ val emulationActivity = NativeLibrary.sEmulationActivity.get()!!
+ emulationActivity.runOnUiThread {
+ fragment = ShaderProgressDialogFragment.newInstance(
+ emulationActivity.getString(R.string.loading),
+ emulationActivity.getString(R.string.preparing_shaders)
+ )
+ fragment.show(emulationActivity.supportFragmentManager, ShaderProgressDialogFragment.TAG)
+ }
+ synchronized(finishLock) { finishLock.wait() }
+ }
+
+ @JvmStatic
+ fun loadProgress(stage: Int, progress: Int, max: Int) {
+ val emulationActivity = NativeLibrary.sEmulationActivity.get()
+ ?: error("[DiskShaderCacheProgress] EmulationActivity not present")
+
+ when (LoadCallbackStage.values()[stage]) {
+ LoadCallbackStage.Prepare -> prepareDialog()
+ LoadCallbackStage.Build -> fragment.onUpdateProgress(
+ emulationActivity.getString(R.string.building_shaders),
+ progress,
+ max
+ )
+ LoadCallbackStage.Complete -> fragment.dismiss()
+ }
+ }
+
+ // Equivalent to VideoCore::LoadCallbackStage
+ enum class LoadCallbackStage {
+ Prepare, Build, Complete
+ }
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ShaderProgressViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ShaderProgressViewModel.kt
new file mode 100644
index 000000000..bf6f0366d
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ShaderProgressViewModel.kt
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.disk_shader_cache
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+
+class ShaderProgressViewModel : ViewModel() {
+ private val _progress = MutableLiveData(0)
+ val progress: LiveData<Int> get() = _progress
+
+ private val _max = MutableLiveData(0)
+ val max: LiveData<Int> get() = _max
+
+ private val _message = MutableLiveData("")
+ val message: LiveData<String> get() = _message
+
+ fun setProgress(progress: Int) {
+ _progress.postValue(progress)
+ }
+
+ fun setMax(max: Int) {
+ _max.postValue(max)
+ }
+
+ fun setMessage(msg: String) {
+ _message.postValue(msg)
+ }
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ui/ShaderProgressDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ui/ShaderProgressDialogFragment.kt
new file mode 100644
index 000000000..2c68c9ac3
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ui/ShaderProgressDialogFragment.kt
@@ -0,0 +1,101 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.yuzu.yuzu_emu.disk_shader_cache.ui
+
+import android.app.Dialog
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.DialogFragment
+import androidx.lifecycle.ViewModelProvider
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
+import org.yuzu.yuzu_emu.disk_shader_cache.DiskShaderCacheProgress
+import org.yuzu.yuzu_emu.disk_shader_cache.ShaderProgressViewModel
+
+class ShaderProgressDialogFragment : DialogFragment() {
+ private var _binding: DialogProgressBarBinding? = null
+ private val binding get() = _binding!!
+
+ private lateinit var alertDialog: AlertDialog
+
+ private lateinit var shaderProgressViewModel: ShaderProgressViewModel
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ _binding = DialogProgressBarBinding.inflate(layoutInflater)
+ shaderProgressViewModel =
+ ViewModelProvider(requireActivity())[ShaderProgressViewModel::class.java]
+
+ val title = requireArguments().getString(TITLE)
+ val message = requireArguments().getString(MESSAGE)
+
+ isCancelable = false
+ alertDialog = MaterialAlertDialogBuilder(requireActivity())
+ .setView(binding.root)
+ .setTitle(title)
+ .setMessage(message)
+ .create()
+ return alertDialog
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ shaderProgressViewModel.progress.observe(viewLifecycleOwner) { progress ->
+ binding.progressBar.progress = progress
+ setUpdateText()
+ }
+ shaderProgressViewModel.max.observe(viewLifecycleOwner) { max ->
+ binding.progressBar.max = max
+ setUpdateText()
+ }
+ shaderProgressViewModel.message.observe(viewLifecycleOwner) { msg ->
+ alertDialog.setMessage(msg)
+ }
+ synchronized(DiskShaderCacheProgress.finishLock) { DiskShaderCacheProgress.finishLock.notifyAll() }
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+
+ fun onUpdateProgress(msg: String, progress: Int, max: Int) {
+ shaderProgressViewModel.setProgress(progress)
+ shaderProgressViewModel.setMax(max)
+ shaderProgressViewModel.setMessage(msg)
+ }
+
+ private fun setUpdateText() {
+ binding.progressText.text = String.format(
+ "%d/%d",
+ shaderProgressViewModel.progress.value,
+ shaderProgressViewModel.max.value
+ )
+ }
+
+ companion object {
+ const val TAG = "ProgressDialogFragment"
+ const val TITLE = "title"
+ const val MESSAGE = "message"
+
+ fun newInstance(title: String, message: String): ShaderProgressDialogFragment {
+ val frag = ShaderProgressDialogFragment()
+ val args = Bundle()
+ args.putString(TITLE, title)
+ args.putString(MESSAGE, message)
+ frag.arguments = args
+ return frag
+ }
+ }
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
index f04b81335..a137d1c3a 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -196,6 +196,8 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
val rendererResolution = rendererSection.getSetting(SettingsFile.KEY_RENDERER_RESOLUTION)
val rendererAspectRatio =
rendererSection.getSetting(SettingsFile.KEY_RENDERER_ASPECT_RATIO)
+ val rendererUseDiskShaderCache =
+ rendererSection.getSetting(SettingsFile.KEY_RENDERER_USE_DISK_SHADER_CACHE)
val rendererForceMaxClocks =
rendererSection.getSetting(SettingsFile.KEY_RENDERER_FORCE_MAX_CLOCK)
val rendererAsynchronousShaders =
@@ -252,6 +254,16 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
)
add(
SwitchSetting(
+ SettingsFile.KEY_RENDERER_USE_DISK_SHADER_CACHE,
+ Settings.SECTION_RENDERER,
+ rendererUseDiskShaderCache,
+ R.string.use_disk_shader_cache,
+ R.string.use_disk_shader_cache_description,
+ true
+ )
+ )
+ add(
+ SwitchSetting(
SettingsFile.KEY_RENDERER_FORCE_MAX_CLOCK,
Settings.SECTION_RENDERER,
rendererForceMaxClocks,
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt
index 37ae39fe6..c518d9ba0 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/utils/SettingsFile.kt
@@ -36,6 +36,7 @@ object SettingsFile {
const val KEY_RENDERER_RESOLUTION = "resolution_setup"
const val KEY_RENDERER_ASPECT_RATIO = "aspect_ratio"
const val KEY_RENDERER_ACCURACY = "gpu_accuracy"
+ const val KEY_RENDERER_USE_DISK_SHADER_CACHE = "use_disk_shader_cache"
const val KEY_RENDERER_ASYNCHRONOUS_SHADERS = "use_asynchronous_shaders"
const val KEY_RENDERER_FORCE_MAX_CLOCK = "force_max_clock"
const val KEY_RENDERER_USE_SPEED_LIMIT = "use_speed_limit"
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp
index d882688f1..0e86dea9e 100644
--- a/src/android/app/src/main/jni/config.cpp
+++ b/src/android/app/src/main/jni/config.cpp
@@ -226,10 +226,6 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.bg_green);
ReadSetting("Renderer", Settings::values.bg_blue);
- // Disable shader cache by default on Android
- Settings::values.use_disk_shader_cache =
- config->GetBoolean("Renderer", "use_disk_shader_cache", false);
-
// Enable force_max_clock by default on Android
Settings::values.renderer_force_max_clock =
config->GetBoolean("Renderer", "force_max_clock", true);
diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp
index 6291c8652..7edadb94a 100644
--- a/src/android/app/src/main/jni/id_cache.cpp
+++ b/src/android/app/src/main/jni/id_cache.cpp
@@ -3,13 +3,18 @@
#include <jni.h>
+#include "common/assert.h"
#include "common/fs/fs_android.h"
#include "jni/applets/software_keyboard.h"
#include "jni/id_cache.h"
+#include "video_core/rasterizer_interface.h"
static JavaVM* s_java_vm;
static jclass s_native_library_class;
+static jclass s_disk_cache_progress_class;
+static jclass s_load_callback_stage_class;
static jmethodID s_exit_emulation_activity;
+static jmethodID s_disk_cache_load_progress;
static constexpr jint JNI_VERSION = JNI_VERSION_1_6;
@@ -38,10 +43,22 @@ jclass GetNativeLibraryClass() {
return s_native_library_class;
}
+jclass GetDiskCacheProgressClass() {
+ return s_disk_cache_progress_class;
+}
+
+jclass GetDiskCacheLoadCallbackStageClass() {
+ return s_load_callback_stage_class;
+}
+
jmethodID GetExitEmulationActivity() {
return s_exit_emulation_activity;
}
+jmethodID GetDiskCacheLoadProgress() {
+ return s_disk_cache_load_progress;
+}
+
} // namespace IDCache
#ifdef __cplusplus
@@ -58,8 +75,16 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// Initialize Java classes
const jclass native_library_class = env->FindClass("org/yuzu/yuzu_emu/NativeLibrary");
s_native_library_class = reinterpret_cast<jclass>(env->NewGlobalRef(native_library_class));
+ s_disk_cache_progress_class = reinterpret_cast<jclass>(env->NewGlobalRef(
+ env->FindClass("org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress")));
+ s_load_callback_stage_class = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass(
+ "org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress$LoadCallbackStage")));
+
+ // Initialize methods
s_exit_emulation_activity =
env->GetStaticMethodID(s_native_library_class, "exitEmulationActivity", "(I)V");
+ s_disk_cache_load_progress =
+ env->GetStaticMethodID(s_disk_cache_progress_class, "loadProgress", "(III)V");
// Initialize Android Storage
Common::FS::Android::RegisterCallbacks(env, s_native_library_class);
@@ -79,6 +104,8 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) {
// UnInitialize Android Storage
Common::FS::Android::UnRegisterCallbacks();
env->DeleteGlobalRef(s_native_library_class);
+ env->DeleteGlobalRef(s_disk_cache_progress_class);
+ env->DeleteGlobalRef(s_load_callback_stage_class);
// UnInitialze applets
SoftwareKeyboard::CleanupJNI(env);
diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h
index 2fe07169d..9337cd254 100644
--- a/src/android/app/src/main/jni/id_cache.h
+++ b/src/android/app/src/main/jni/id_cache.h
@@ -2,10 +2,15 @@
#include <jni.h>
+#include "video_core/rasterizer_interface.h"
+
namespace IDCache {
JNIEnv* GetEnvForThread();
jclass GetNativeLibraryClass();
+jclass GetDiskCacheProgressClass();
+jclass GetDiskCacheLoadCallbackStageClass();
jmethodID GetExitEmulationActivity();
+jmethodID GetDiskCacheLoadProgress();
} // namespace IDCache
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 55736bce2..b10c55a45 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -51,6 +51,7 @@
#include "jni/emu_window/emu_window.h"
#include "jni/id_cache.h"
#include "video_core/rasterizer_interface.h"
+#include "video_core/renderer_base.h"
namespace {
@@ -229,6 +230,15 @@ public:
m_is_running = true;
}
+ // Load the disk shader cache.
+ if (Settings::values.use_disk_shader_cache.GetValue()) {
+ LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
+ m_system.Renderer().ReadRasterizer()->LoadDiskResources(
+ m_system.GetApplicationProcessProgramID(), std::stop_token{},
+ LoadDiskCacheProgress);
+ LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
+ }
+
void(m_system.Run());
if (m_system.DebuggerEnabled()) {
@@ -296,6 +306,14 @@ private:
}
private:
+ static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max) {
+ JNIEnv* env = IDCache::GetEnvForThread();
+ env->CallStaticVoidMethod(IDCache::GetDiskCacheProgressClass(),
+ IDCache::GetDiskCacheLoadProgress(), static_cast<jint>(stage),
+ static_cast<jint>(progress), static_cast<jint>(max));
+ }
+
+private:
static EmulationSession s_instance;
// Frontend management
diff --git a/src/android/app/src/main/res/layout/dialog_progress_bar.xml b/src/android/app/src/main/res/layout/dialog_progress_bar.xml
index 1dbfd4f7b..d17711a65 100644
--- a/src/android/app/src/main/res/layout/dialog_progress_bar.xml
+++ b/src/android/app/src/main/res/layout/dialog_progress_bar.xml
@@ -12,4 +12,13 @@
android:layout_margin="24dp"
app:trackCornerRadius="4dp" />
+ <TextView
+ android:id="@+id/progress_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="24dp"
+ android:layout_marginRight="24dp"
+ android:layout_marginBottom="24dp"
+ android:gravity="end" />
+
</LinearLayout>
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 70bff5749..45a9694d4 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -35,6 +35,8 @@
<string name="renderer_asynchronous_shaders_description">Compiles shaders asynchronously, which will reduce stutter but may introduce glitches.</string>
<string name="renderer_debug">Enable graphics debugging</string>
<string name="renderer_debug_description">When checked, the graphics API enters a slower debugging mode.</string>
+ <string name="use_disk_shader_cache">Use disk shader cache</string>
+ <string name="use_disk_shader_cache_description">Reduce stuttering by storing and loading generated shaders to disk.</string>
<!-- Audio settings strings -->
<string name="audio_volume">Volume</string>
@@ -45,6 +47,7 @@
<string name="ini_saved">Saved settings</string>
<string name="gameid_saved">Saved settings for %1$s</string>
<string name="error_saving">Error saving %1$s.ini: %2$s</string>
+ <string name="loading">Loading...</string>
<!-- Game Grid Screen-->
<string name="grid_menu_core_settings">Settings</string>
@@ -183,4 +186,8 @@
<string name="gamepad_home">Home</string>
<string name="gamepad_screenshot">Screenshot</string>
+ <!-- Disk shader cache -->
+ <string name="preparing_shaders">Preparing shaders</string>
+ <string name="building_shaders">Building shaders</string>
+
</resources>